package top.yangbuyi.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.yangbuyi.constants.LoginConstant;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static top.yangbuyi.constants.LoginConstant.QUERY_ADMIN_SQL;

/**
 * @program: coinex-change
 * @ClassName: UserServcieDetailsServiceImpl
 * @create: 2021-01-23 15:25
 * @author: yangshuai
 * @since： JDK1.8
 * @UserServcieDetailsServiceImpl: 用户资源管理$登陆授权
 **/
@SuppressWarnings("all")
@Service
public class UserServiceDetailsServiceImpl implements UserDetailsService {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	/**
	 * @功能描述:根据用户名称获取用户信息
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/23 15:26
	 */
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		// 区分登陆类型
		String loginType = requestAttributes.getRequest().getParameter("login_type");
		if (StringUtils.isEmpty(loginType)) {
			// 抛异常
			throw new AuthenticationServiceException("缺少登陆类型");
		}
		UserDetails userDetails = null;
		try {
			// 判断登陆类型
			switch (loginType) {
				case LoginConstant.ADMIN_TYPE:
					// 管理员登陆
					userDetails = loadSysUserByUsername(username);
					break;
				case LoginConstant.MEMBER_TYPE:
					//  会员登陆
					userDetails = loadMemberUserByUsername(username);
					break;
				default:
					throw new AuthenticationServiceException("暂不支持的登陆方式:" + loginType);
			}
		} catch (IncorrectResultSizeDataAccessException e) {
			// 会员不存在
			throw new UsernameNotFoundException("会员：" + username + "不存在");
		}
		return userDetails;
	}


	/**
	 * @功能描述:后台人员的登陆(管理员)
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/23 15:42
	 */
	private UserDetails loadSysUserByUsername(String username) {
		// TODD 使用用户名称查询该用户是否存在
		return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_SQL, new RowMapper<User>() {
			@Override
			public User mapRow(ResultSet rs, int rowNum) throws SQLException {
				if (rs.wasNull()) {
					throw new UsernameNotFoundException("用户：" + username + "不存在");
				}
				Long id = rs.getLong("id");
				String password = rs.getString("password");
				int status = rs.getInt("status");
				// TODD 封装成一个 UserDetails 对象 返回
				User user = new User(
						// 用户ID 作为用户名称
						String.valueOf(id),
						password,
						status == 1,
						true,
						true,
						true,
						getUserPermissions(id)); // 后台人员登陆的角色权限
				return user;
			}
		}, username);
	}

	/**
	 * @功能描述:前端页面：会员用户登陆
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/23 15:42
	 */
	private UserDetails loadMemberUserByUsername(String username) {
		// TODD 使用用户名称查询该用户是否存在
		return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_SQL, new RowMapper<User>() {
			@Override
			public User mapRow(ResultSet resultSet, int i) throws SQLException {
				if (resultSet.wasNull()) {
					throw new UsernameNotFoundException("会员用户：" + username + "不存在");
				}
				long id = resultSet.getLong("id"); // 获取用户的id
				String password = resultSet.getString("password");
				int status = resultSet.getInt("status");
				return new User(
						String.valueOf(id),
						password,
						status == 1,
						true, // 没有过期
						true, // 没有被锁
						true,
						Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")) // 前端页面会员登陆的唯一角色
				);
			}
		}, username, username);
	}

	/**
	 * @功能描述:查询这个用户对应的权限
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/24 12:10
	 */
	private Collection<? extends GrantedAuthority> getUserPermissions(Long id) {
		// 1.当用户为超级管理员时，他拥有所有的权限数据
		String roleCode = jdbcTemplate.queryForObject(LoginConstant.QUERY_ROLE_CODE_SQL, String.class, id);
		// 存储用户的权限数据 *:* 全部
		List<String> permissions = null;
		// 2.判断是否为超级管理员CODE
		if (LoginConstant.ADMIN_ROLE_CODE.equals(roleCode)) {
			permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_ALL_PERMISSIONS, String.class);
		} else {
			// 普通用户，需要使用角色->权限数据
			permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_PERMISSION_SQL, String.class, id);
		}
		// 判断是否为空则直接返回空集合
		if (permissions == null || permissions.isEmpty()) {
			return Collections.emptySet();
		}
		// 去重权限标识 返回出来
		return permissions.stream()
				.distinct() // 去重
				.map(params -> new SimpleGrantedAuthority(params))
				.collect(Collectors.toSet());
	}


}
